﻿using System;
using System.Activities.Statements;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using KL.UFrame.Core.Exception;
using KL.UFrame.Core.Result;
using KL.UFrame.Data.Entities;
using KL.UFrame.Data.Models;

namespace KL.UFrame.Data.Business.Impl
{
    public class TrainningBusiness : BusinessBase, ITrainningBusiness
    {
        public async Task<int> CreateCategoryAsync(TrainningCategoryModel model)
        {
            var category=new TrainningCategory
            {
                Name = model.Name,
                Enabled = model.Enabled,
                CreateId = model.CreateId,
                CreateTime = model.CreateTime
            };
            Db.Entry(category).State= EntityState.Added;
            var result = await Db.SaveChangesAsync();
            if (result > 0) return category.Id;
            throw new ResultException(-501,"创建培训分类失败");
        }

        public async Task<int> CreateEnrollAsync(EnrollModel model)
        {
            using (var tans = Db.Database.BeginTransaction())
            {
                var enrollCount = await Db.Enrolls.CountAsync(a => a.TrainningId == model.TrainningId
                                                              && a.EnrollStatus != EnrollStatus.Failed);
                var limit = (await Db.Trainnings.FindAsync(model.TrainningId))?.UserLimit ?? 0;

                if (enrollCount < limit)
                {
                    var enroll = new Enroll
                    {
                        Name = model.Name,
                        IdCard = model.IdCard,
                        Phone = model.Phone,
                        Age = model.Age,
                        Gender = model.Gender,
                        TrainningId = model.TrainningId,
                        CreateTime = model.CreateTime,
                        EnrollStatus = EnrollStatus.New
                    };
                    Db.Entry(enroll).State = EntityState.Added;
                    var result = await Db.SaveChangesAsync();
                    if (result > 0)
                    {
                        tans.Commit();
                        return enroll.Id;
                    }
                    throw new ResultException(-501, "创建报名记录失败");
                }
                return -1; //超出名额
            }
        }

        public async Task<int> CreateTrainningAsync(TrainningModel model)
        {
            var train = new Trainning
            {
                Title = model.Title,
                UserLimit = model.UserLimit,
                CategoryId = model.CategoryId,
                CreateId = model.CreateId,
                CreateTime = model.CreateTime,
                Enabled = model.Enabled
            };
            Db.Entry(train).State= EntityState.Added;
            var result = await Db.SaveChangesAsync();
            if (result > 0) return train.Id;
            throw new ResultException(-501,"创建培训失败");
        }

        public async Task<bool> DeleteCategoryAsync(int id)
        {
            var category = await Db.TrainningCategories.FindAsync(id);
            if(category==null) throw new ResultException(-404,$"Id为{id}的培训分类不存在");
            if (!category.Enabled) return true;
            category.Enabled = false;
            Db.Entry(category).State= EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }

        public async Task<bool> DeleteTrainningAsync(int id)
        {
            var trainning = await Db.Trainnings.FindAsync(id);
            if (trainning == null) throw new ResultException(-404, $"Id为{id}的培训不存在");
            if (!trainning.Enabled) return true;
            trainning.Enabled = false;
            Db.Entry(trainning).State = EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }

        public async Task<ResultMessage<List<TrainningCategoryModel>>> GetAllCategoriesAsync(bool onlyEnabled = true)
        {
            var query =await Db.TrainningCategories.Include(a=>a.CreateUser).Include(b=>b.UpdateUser).AsNoTracking()
                .Where(a => (onlyEnabled && a.Enabled) || !onlyEnabled)
                .Select(a => new TrainningCategoryModel
                {
                    Id = a.Id,
                    Name = a.Name,
                    CreateId = a.CreateId,
                    CreateTime = a.CreateTime,
                    Enabled = a.Enabled,
                    CreateUser = a.CreateUser.RealName,
                    UpdateId = a.UpdateId,
                    UpdateTime = a.UpdateTime,
                    UpdateUser = a.UpdateUser.RealName
                }).ToListAsync();
            return new ResultMessage<List<TrainningCategoryModel>>(query);
        }

        public async Task<ResultMessage<List<TrainningModel>>> GetAllTrainningsAsync(int categoryId, bool onlyEnabled = true)
        {
            var result = await Db.Trainnings.Include(a => a.Category).Include(a=>a.CreateUser)
                .Where(a => a.CategoryId == categoryId)
                .Where(a => (a.Enabled && onlyEnabled) || !onlyEnabled)
                .Select(a => new TrainningModel
                {
                    Id = a.Id,
                    Title = a.Title,
                    CategoryId = a.CategoryId,
                    Category = a.Category.Name,
                    Enabled = a.Enabled,
                    CreateId = a.CreateId,
                    CreateTime = a.CreateTime,
                    CreateUser = a.CreateUser.RealName,
                    UserLimit = a.UserLimit
                }).ToListAsync();
            return new ResultMessage<List<TrainningModel>>(result);
        }

        public async Task<TrainningCategoryModel> GetCategoryAsync(int id)
        {
            var category = await Db.TrainningCategories.Include(a => a.CreateUser).SingleOrDefaultAsync(a => a.Id == id);
            if(category==null) throw new ResultException(-404, $"编号为{id}的培训分类不存在");
            return new TrainningCategoryModel
            {
                Id = id,
                Name = category.Name,
                Enabled = category.Enabled,
                CreateId = category.CreateId,
                CreateTime = category.CreateTime,
                CreateUser = category.CreateUser.RealName
            };
        }

        public async Task<TrainningModel> GetTrainningAsync(int id)
        {
            var trainning = await Db.Trainnings.Include(a=>a.Category).Include(a => a.CreateUser).SingleOrDefaultAsync(a => a.Id == id);
            if (trainning==null) throw new ResultException(-404,$"编号为{id}的培训不存在");
            return new TrainningModel
            {
                Id = id,
                CreateId = trainning.CreateId,
                Title = trainning.Title,
                Enabled = trainning.Enabled,
                Category = trainning.Category.Name,
                CategoryId = trainning.CategoryId,
                CreateUser = trainning.CreateUser.RealName,
                CreateTime = trainning.CreateTime,
                UserLimit = trainning.UserLimit
            };
        }

        public async Task<bool> ResumeCategoryAsync(int id)
        {
            var item = await Db.TrainningCategories.FindAsync(id);
            if (item == null) throw new ResultException(-404, $"Id为{id}的培训分类不存在");
            if (item.Enabled) return true;
            item.Enabled = true;
            Db.Entry(item).State = EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }

        public async Task<bool> ResumeTrainningAsync(int id)
        {
            var item = await Db.Trainnings.FindAsync(id);
            if (item == null) throw new ResultException(-404, $"Id为{id}的培训不存在");
            if (item.Enabled) return true;
            item.Enabled = true;
            Db.Entry(item).State = EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }

        public async Task<ResultMessage<List<EnrollModel>>> SearchEnrollsAsync(int trainningId,string phone,
            DateTime start, DateTime end, int pageIndex, int pageSize)
        {
            var query =
                Db.Enrolls.Include(a=>a.Trainning).AsNoTracking()
                    .Where(a=>string.IsNullOrEmpty(phone) || a.Phone==phone)
                    .Where(a => trainningId<=0 || a.TrainningId == trainningId ).Where(a=> a.CreateTime >= start && a.CreateTime <= end);
            var count = await query.CountAsync();
            var result = await query.OrderByDescending(a=>a.CreateTime).Skip((pageIndex - 1)*pageIndex).Take(pageSize)
                .Select(a => new EnrollModel
                {
                    Id = a.Id,
                    Name = a.Name,
                    Age = a.Age,
                    Gender = a.Gender,
                    IdCard = a.IdCard,
                    Phone = a.Phone,
                    TrainningId = a.TrainningId,
                    CreateTime = a.CreateTime,
                    EnrollStatus=a.EnrollStatus,
                    StatusDescription = a.StatusDescription,
                    TrainningName = a.Trainning.Title
                }).ToListAsync();
            return new ResultMessage<List<EnrollModel>>(result, count);
        }

        public async Task<int> UpdateCategoryAsync(TrainningCategoryModel model)
        {
            var category = await Db.TrainningCategories.FindAsync(model.Id);
            if(category==null) throw new ResultException(-404,$"编号为{model.Id}的培训分类不存在");
            category.Name = model.Name;
            category.Enabled = model.Enabled;
            category.UpdateTime = model.UpdateTime;
            category.UpdateId = model.UpdateId;
            Db.Entry(category).State= EntityState.Modified;
            if (await Db.SaveChangesAsync() > 0) return model.Id;
            throw new ResultException(-501,"更新培训分类失败");
        }

        public async Task<int> UpdateTrainningAsync(TrainningModel model)
        {
            var trainning = await Db.Trainnings.FindAsync(model.Id);
            if (trainning == null) throw new ResultException(-404, $"编号为{model.Id}的培训不存在");
            trainning.Title = model.Title;
            trainning.CategoryId = model.CategoryId;
            trainning.UserLimit = model.UserLimit;
            trainning.Enabled = model.Enabled;
            trainning.UpdateTime = model.UpdateTime;
            trainning.UpdateId = model.UpdateId;
            Db.Entry(trainning).State = EntityState.Modified;
            if (await Db.SaveChangesAsync() > 0) return model.Id;
            throw new ResultException(-501, "更新培训失败");
        }

        public async Task<List<EnrollSummaryModel>> GetEnrollsAsync(string phone, string idCard,DateTime start,DateTime end)
        {
            var result =
                await
                    Db.Enrolls.Include(a=>a.Trainning).Where(
                        a => a.Phone == phone && a.IdCard == idCard && a.CreateTime >= start && a.CreateTime <= end)
                        .AsNoTracking().Select(a => new EnrollSummaryModel
                        {
                            Name = a.Name,
                            TrainningName = a.Trainning.Title,
                            CreateTime = a.CreateTime,
                            Status = a.EnrollStatus== EnrollStatus.Pass ?"通过":a.EnrollStatus== EnrollStatus.Failed ?"未通过":"未审核",
                            StatusDescription = a.StatusDescription
                        }).ToListAsync();
            return result;
        }

        public async Task<object> GetCategoryiesWithTrainnings()
        {
            var result= await Db.TrainningCategories.Include(a=>a.Trainnings)
                .AsNoTracking().ToListAsync();
            return result
                .Select(a => new
                {
                    a.Id,
                    a.Name,
                    Trainnings = a.Trainnings?.Select(b => new {b.Id, b.Title}).ToList()
                }).ToList();
        }

        public async Task<bool> AuditAsync(int enrollId, EnrollStatus status, string description)
        {
            var enroll = await Db.Enrolls.FindAsync(enrollId);
            if (enroll == null)  throw new ResultException(-400,$"编号为{enrollId}的报名记录不存在");

            enroll.EnrollStatus = status;
            enroll.StatusDescription = description;

            Db.Entry(enroll).State= EntityState.Modified;
            return await Db.SaveChangesAsync() > 0;
        }
    }
}
